package main

func main() {

}

// 构造一个计算语义的Map，避免重复比较
var StrBeddingMap map[string]float64

const ExceedN = 10000 // mock
func splitSemanticText(text string, p, t float64) []string {
	// 实现目标：根据相邻chunk进行语义合并，每次找到相似度最高的相邻chunk  并且将chunk合并到比例和原始比例小于p的时候，可以返回
	//         或者当所有的相似度，都小于t的时候，可以返回

	// 思路1：使用广度优先的写法，粗暴迭代，cache emBedding 和 calcSimilarity
	//       先实现，再考虑对应优化策略，如动态规划？记忆化搜索？怎么优化？
	StrBeddingMap = make(map[string]float64)

	// 拿到原始chunk及长度
	chunkQueue := splitSentences(text)
	oriLen := len(chunkQueue)

	// 广度优先遍历, 正常迭代
	for len(chunkQueue) > 0 {
		currLen := len(chunkQueue)
		// 计算退出的第一个边界, 比例低于p
		if float64(currLen)/float64(oriLen) < p {
			return chunkQueue
		}

		var maxSimilarity float64 // 默认calcSimilarity计算出来的相关性都为正数
		var mergeItem int

		for i := 0; i < currLen-1; i++ {
			// 开始计算相关性
			similarity := calcSimilarity(cacheEmBedding(chunkQueue[i]), cacheEmBedding(chunkQueue[i+1]))
			if similarity > maxSimilarity {
				maxSimilarity = similarity
				mergeItem = i
			}
		}
		// 遍历完成，计算第二个边界，拿到最大的maxSimilarity， 判定是否超出阈值t，没有的话，直接返回，说明相邻之间无法合并了
		if maxSimilarity < t {
			return chunkQueue
		}
		// 可以合并，继续处理, 合并i和i+1
		mergeStr := chunkQueue[mergeItem] + chunkQueue[mergeItem+1]
		chunkQueue = append(append(chunkQueue[:mergeItem], mergeStr), chunkQueue[mergeItem+2:]...)
	}

	return nil
}

func splitSentences(str string) []string { // 原始的切分函数
	return nil
}

func cacheEmBedding(text string) float64 {
	if res, has := StrBeddingMap[text]; has {
		return res
	}
	StrBeddingMap[text] = emBedding(text)
	return StrBeddingMap[text]
}

func emBedding(text string) float64 { // 计算文本的多纬语义， 有文本长度限制N，超出直接报错
	if len(text) > ExceedN {
		return -1
	}
	// do something
	return 0
}

func calcSimilarity(vec1, vec2 float64) float64 { // 计算两个的相似度
	// do something
	return 0
}
